#pragma once
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Socket.hpp"
#include <poll.h>

using namespace LogModule;
using namespace InetAddrModule;
using namespace SocketModule;

const int NUM = 4096;
const int gdefaultfd = -1;

class PollSever
{
private:
    void Accepter()
    {
        InetAddr peer;
        int newfd = _listen_socketfd->Accepter(&peer);
        if(newfd < 0)
            return;
        
        LOG(LogLevel::DEBUG) << "获得一个新连接：" << peer.Addr();

        int pos = -1;
        for(int i = 0;i < NUM;i++)
        {
            if(_fds[i].fd == gdefaultfd)
            {
                pos = i;
                break;
            }
        }
        if(pos == -1)
        {
            // 这里实际上可以自动进行扩容的
            LOG(LogLevel::WARNING) << "服务器已达到最大连接数";
            close(newfd);
        }
        else
        {
            _fds[pos].fd = newfd;
            _fds[pos].events = POLLIN;
        }
    }
    void Recver(int who)
    {
        char buffer[1024];
        ssize_t n = recv(_fds[who].fd, buffer, sizeof(buffer) - 1, 0); 
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << "client# " << buffer << std::endl;

            std::string message = "echo# ";
            message += buffer;
            send(_fds[who].fd, message.c_str(), message.size(), 0); 
        }
        else if (n == 0)
        {
            LOG(LogLevel::DEBUG) << "客户端退出, sockfd: " << _fds[who].fd;
            close(_fds[who].fd);
            _fds[who].fd = gdefaultfd;
            _fds[who].events = 0;
            _fds[who].revents = 0;
        }
        else
        {
            LOG(LogLevel::DEBUG) << "客户端读取出错, sockfd: " << _fds[who].fd;
            close(_fds[who].fd);
            _fds[who].fd = gdefaultfd;
            _fds[who].events = 0;
            _fds[who].revents = 0;
        }
    }
    void Dispatcher()
    {
        for(int i = 0 ;i < NUM;i++)
        {
            if(_fds[i].fd == gdefaultfd)
                continue;
            // 两种情况：listen socket 或者 读文件描述符 就绪
            if(_fds[i].fd == _listen_socketfd->Fd())
            {
                if(_fds[i].revents & POLLIN)
                {
                    Accepter();
                }
            }
            else
            {
                if(_fds[i].revents & POLLIN)
                {
                    Recver(i);
                }
            }
        }
    }
public:
    PollSever(uint16_t port):
        _port(port),
        _listen_socketfd(std::make_unique<TcpSocket>()),
        _running(false)
    {}
    void Init()
    {
        _listen_socketfd->BuildTcpSocketMethod(_port);
        for(int i = 0 ;i < NUM;i++)
        {
            _fds[i].fd = gdefaultfd;
            _fds[i].events = 0;
            _fds[i].revents = 0;
        }
        
        _fds[0].fd = _listen_socketfd->Fd();
        _fds[0].events |= POLLIN;
    }
    void Loop()
    {
        _running = true;

        int timeout = -1;//单位：毫秒
        while(_running)
        {
            // 调用poll等待
            int n = ::poll(_fds,NUM,timeout);

            if(n < 0)
            {
                LOG(LogLevel::FATAL) << "select failed";
                break;
            }
            else if(n == 0)
            {
                LOG(LogLevel::ERROR) << "数据未就绪, timeout……";
            }
            else
            {
                LOG(LogLevel::DEBUG) << "事件已就绪……";
                Dispatcher();
            }
            sleep(1);
        }
        _running = false;
    }
    ~PollSever()
    {}
private:
    uint16_t _port;
    std::unique_ptr<Socket> _listen_socketfd;
    bool _running;
    struct pollfd _fds[NUM];
};

